﻿using DAL.Database.Db;
using Infra.Tools.Logging;
using Infra.Utils.ExpressionTree;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace BLL.Service.Basis
{
    public abstract class Kernel<T> : IKernel<T>
        where T : class, new()
    {
        protected readonly IRepository<T> _repository;

        public abstract T Insert(T entity);
        public abstract void Delete(T entity);
        public abstract void Delete(Expression<Func<T, bool>> predicate);
        public abstract void Update(T entity);
        public abstract void Update(Expression<Func<T, bool>> predicate, Action<T> action);

        public abstract T InsertIfNotExist(T entity);
        public abstract T InsertIfNotExist(Expression<Func<T, bool>> predicate, T entity);

        public abstract T InsertOrUpdate(Expression<Func<T, bool>> predicate, T entity, Action<T> action);

        public abstract void Restore(T entity);

        #region Costructors
        protected Kernel(IRepositoryFactory factory, ILogger logger)
        {
            this._repository = factory.Create<T>(logger);
        }
        #endregion

        public virtual int Count
        {
            get
            {
                return this._repository.Count;
            }
        }

        public virtual IQueryable<T> All()
        {
            return this._repository.All();
        }

        public IEnumerable<T> Filter(T entity, IQueryManager querymanager)
        {
            return this._repository.Filter(entity, querymanager);
        }

        public virtual IQueryable<T> Filter(Expression<Func<T, bool>> predicate)
        {
            return this._repository.Filter(predicate);
        }

        public virtual IQueryable<T> Filter(Expression<Func<T, bool>> filter, out int total, int index = 0, int size = 50)
        {
            return this._repository.Filter(filter, out total, index, size);
        }

        public virtual IEnumerable<T> Filter(T entity, IQueryManager querymanager, out int total, int index = 0, int size = 50)
        {
            return this._repository.Filter(entity, querymanager, out total, index, size);
        }

        public virtual bool Contains(Expression<Func<T, bool>> predicate)
        {
            return this._repository.Contains(predicate);
        }

        public virtual T Find(T entity)
        {
            return this._repository.Find(entity);
        }

        public virtual T Find(params object[] keys)
        {
            return this._repository.Find(keys);
        }

        public virtual T Find(Expression<Func<T, bool>> predicate)
        {
            return this._repository.Find(predicate);
        }

        public virtual void Dispose()
        {
            if (this._repository != null)
                this._repository.Dispose();
        }
    }
}
